package com.gaff.emp.core.modules.auth;

import cn.hutool.core.util.StrUtil;
import com.gaff.emp.core.util.Identities;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class JwtUtil {

    private static final long EXPIRE_TIME = 12 * 60 * 60 * 1000;

    private static final String SECRET = "gaffassen-secret";

    private static final Cache<String, LoginUserInfo> sessions = CacheBuilder.newBuilder()
            .initialCapacity(1000)
            .concurrencyLevel(Runtime.getRuntime().availableProcessors())
            .expireAfterAccess(30 * 60, TimeUnit.SECONDS)
            .build();

    public static void clearUserInfo(LoginUserInfo userInfo) {
        sessions.invalidate(userInfo.getUuid());
    }

    public static String generateToken(LoginUserInfo userDetail) {
        userDetail.setUuid(Identities.uuid());
        Map<String, Object> claims = new HashMap<>();
        claims.put("sessionKey", userDetail.getUuid());
        Date expirationDate = new Date(System.currentTimeMillis() + EXPIRE_TIME);
        sessions.put(userDetail.getUuid(), userDetail);
        return Jwts.builder().setClaims(claims).setExpiration(expirationDate).signWith(SignatureAlgorithm.HS512, SECRET).compact();
    }

    public static LoginUserInfo getUserInfoFromToken(String token) {
        if (StrUtil.isBlank(token)) {
            return null;
        }
        Claims claims = getClaimsFromToken(token);
        if (claims == null) {
            return null;
        }
        Date expiration = claims.getExpiration();
        if (expiration.before(new Date())) {
            return null;
        }
        String uuid = (String) claims.get("sessionKey");
        if (StrUtil.isNotBlank(uuid)) {
            return sessions.getIfPresent(uuid);
        }
        return null;
    }

    private static Claims getClaimsFromToken(String token) {
        Claims claims;
        try {
            claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
        } catch (Exception e) {
            claims = null;
        }
        return claims;
    }

}
